// PropPagePing.cpp : implementation file
//

#include "stdafx.h"
#include "NetTools.h"
#include "PropPagePing.h"

// CPropPagePing dialog

IMPLEMENT_DYNAMIC(CPropPagePing, CPropertyPage)

CPropPagePing::CPropPagePing()
	: CPropertyPage(CPropPagePing::IDD)
{
}

CPropPagePing::~CPropPagePing()
{
}

void CPropPagePing::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT_HOSTNAME, m_oEditHostname);
	DDX_Control(pDX, IDC_LIST_RESULTS, m_oListResults);
}

BEGIN_MESSAGE_MAP(CPropPagePing, CPropertyPage)
	ON_BN_CLICKED(IDC_BUTTON_PING, &CPropPagePing::OnBnClickedButtonPing)
	ON_BN_CLICKED(IDC_BUTTON_TRACEROUTE, &CPropPagePing::OnBnClickedButtonTraceroute)
	ON_MESSAGE(UWM_PING_REPLY, &CPropPagePing::OnPingResult)
	ON_MESSAGE(UWM_TRACEROUTE_REPLY, &CPropPagePing::OnTraceRouteResult)
END_MESSAGE_MAP()

// CPropPagePing message handlers

BOOL CPropPagePing::OnInitDialog() 
{
	CPropertyPage::OnInitDialog();

	m_oListResults.InsertColumn(0, _T("I.P. Address"), LVCFMT_LEFT, 150);
	m_oListResults.InsertColumn(1, _T("RTT"), LVCFMT_LEFT, 50);

	m_oIcmp.SetCallback(GetSafeHwnd());
	
	return TRUE;
}

void CPropPagePing::OnBnClickedButtonPing()
{
	CWaitCursor cur;

	m_oListResults.DeleteAllItems();

	CString sAddress;
	m_oEditHostname.GetWindowText(sAddress);

#if 0
	m_oIcmp.Ping(sAddress);
#else
	char szHost[256];
	ustrncpy(szHost, sAddress, 256);

	DWORD dwAddress = inet_addr(szHost);
	if(INADDR_NONE == dwAddress)
	{
		hostent* host = gethostbyname(szHost);
		if(host)
		{
			memcpy(&dwAddress, host->h_addr, host->h_length);
		}
		else
		{
			AfxMessageBox(_T("Failed to resolve hostname"));
			return;
		}
	}

	HANDLE hICmp = IcmpCreateFile();
	for(int i = 0; i < 5; i++)
	{
		CIcmpReply* pReply = new CIcmpReply;
		pReply->m_dwAddress = dwAddress;

		DWORD dw = IcmpSendEcho(hICmp, dwAddress, 0,0, NULL, pReply, sizeof(icmp_echo_reply),500);

		if(ERROR_SUCCESS != pReply->m_dwError)
		{
			CString sError = GetWin32ErrorString(pReply->m_dwError);
			m_oListResults.InsertItem(m_oListResults.GetItemCount(), sError, 0);
		}
		else
		{
			in_addr Address;
			Address.S_un.S_addr = pReply->Address;

			CString sRetAddress;
			sRetAddress.Format(_T("%d.%d.%d.%d"), 
								Address.S_un.S_un_b.s_b1,
								Address.S_un.S_un_b.s_b2,
								Address.S_un.S_un_b.s_b3,
								Address.S_un.S_un_b.s_b4);

			CString sRTT;
			sRTT.Format(_T("%ld"), pReply->RoundTripTime);

			int nItem = m_oListResults.InsertItem(m_oListResults.GetItemCount(), sRetAddress, 0);
			m_oListResults.SetItem(nItem, 1, LVIF_TEXT, sRTT, 0, 0, 0, 0);
		}
		delete pReply;
	}
	IcmpCloseHandle(hICmp);
#endif
}

void CPropPagePing::OnBnClickedButtonTraceroute()
{
	CWaitCursor cur;

	m_oListResults.DeleteAllItems();

	CString sAddress;
	m_oEditHostname.GetWindowText(sAddress);
#if 0
	m_oIcmp.TraceRoute(sAddress);
#else
	char szHost[256];
	ustrncpy(szHost, sAddress, 256);

	DWORD dwAddress = inet_addr(szHost);
	if(INADDR_NONE == dwAddress)
	{
		hostent* host = gethostbyname(szHost);
		if(host)
		{
			memcpy(&dwAddress, host->h_addr, host->h_length);
		}
		else
		{
			AfxMessageBox(_T("Failed to resolve hostname"));
			return;
		}
	}

	HANDLE hICmp = IcmpCreateFile();
	for(int nIdx = 1; nIdx < 254; nIdx++)
	{
		CIcmpReply* pReply = new CIcmpReply;
		pReply->m_dwAddress = dwAddress;

		ip_option_information ioi;
		memset(&ioi, 0, sizeof(ip_option_information));
		ioi.Ttl = nIdx;

		DWORD dw = IcmpSendEcho(hICmp, dwAddress, 0,0, &ioi, pReply, sizeof(icmp_echo_reply),500);
		if(0 == dw)
		{
			pReply->m_dwError = GetLastError();
		}
		if(ERROR_SUCCESS != pReply->m_dwError)
		{
			CString sError = GetWin32ErrorString(pReply->m_dwError);
			m_oListResults.InsertItem(m_oListResults.GetItemCount(), sError, 0);
		}
		else
		{
			in_addr Address;
			Address.S_un.S_addr = pReply->Address;

			CString sRetAddress;
			sRetAddress.Format(_T("%d.%d.%d.%d"), 
								Address.S_un.S_un_b.s_b1,
								Address.S_un.S_un_b.s_b2,
								Address.S_un.S_un_b.s_b3,
								Address.S_un.S_un_b.s_b4);

			CString sRTT;
			sRTT.Format(_T("%ld"), pReply->RoundTripTime);

			int nItem = m_oListResults.InsertItem(m_oListResults.GetItemCount(), sRetAddress, 0);
			m_oListResults.SetItem(nItem, 1, LVIF_TEXT, sRTT, 0, 0, 0, 0);
		}
		if(pReply->Address == dwAddress)
		{
			delete pReply;
			break;
		}
		delete pReply;
	}
	IcmpCloseHandle(hICmp);
#endif
}

LONG CPropPagePing::OnPingResult(WPARAM wParam, LPARAM lParam)
{
	CIcmpReply* pReply = (CIcmpReply*)lParam;

	if(pReply)
	{
		if(ERROR_SUCCESS != pReply->m_dwError)
		{
			CString sError = GetWin32ErrorString(pReply->m_dwError);
			m_oListResults.InsertItem(m_oListResults.GetItemCount(), sError, 0);
		}
		else
		{
			in_addr Address;
			Address.S_un.S_addr = pReply->Address;

			CString sRetAddress;
			sRetAddress.Format(_T("%d.%d.%d.%d"), 
								Address.S_un.S_un_b.s_b1,
								Address.S_un.S_un_b.s_b2,
								Address.S_un.S_un_b.s_b3,
								Address.S_un.S_un_b.s_b4);

			CString sRTT;
			sRTT.Format(_T("%ld"), pReply->RoundTripTime);

			int nItem = m_oListResults.InsertItem(m_oListResults.GetItemCount(), sRetAddress, 0);
			m_oListResults.SetItem(nItem, 1, LVIF_TEXT, sRTT, 0, 0, 0, 0);
		}
		delete pReply;
	}

	return ERROR_SUCCESS;
}

LONG CPropPagePing::OnTraceRouteResult(WPARAM wParam, LPARAM lParam)
{
	CIcmpReply* pReply = (CIcmpReply*)lParam;

	if(pReply)
	{
		if(ERROR_SUCCESS != pReply->m_dwError)
		{
			CString sError = GetWin32ErrorString(pReply->m_dwError);
			m_oListResults.InsertItem(m_oListResults.GetItemCount(), sError, 0);
		}
		else
		{
			in_addr Address;
			Address.S_un.S_addr = pReply->Address;

			CString sRetAddress;
			sRetAddress.Format(_T("%d.%d.%d.%d"), 
								Address.S_un.S_un_b.s_b1,
								Address.S_un.S_un_b.s_b2,
								Address.S_un.S_un_b.s_b3,
								Address.S_un.S_un_b.s_b4);

			CString sRTT;
			sRTT.Format(_T("%ld"), pReply->RoundTripTime);

			int nItem = m_oListResults.InsertItem(m_oListResults.GetItemCount(), sRetAddress, 0);
			m_oListResults.SetItem(nItem, 1, LVIF_TEXT, sRTT, 0, 0, 0, 0);
		}

		delete pReply;
	}

	return ERROR_SUCCESS;
}
